package qscript;

import g4p_controls.G4P;
import g4p_controls.GAlign;
import g4p_controls.GButton;
import g4p_controls.GCScheme;
import g4p_controls.GEvent;
import g4p_controls.GLabel;
import g4p_controls.GOption;
import g4p_controls.GPanel;
import g4p_controls.GSlider;
import g4p_controls.GTextField;
import g4p_controls.GToggleGroup;
import grafica.GPlot;
import grafica.GPoint;
import grafica.GPointsArray;

import java.awt.Color;

import org.qscript.Result;
import org.qscript.Script;
import org.qscript.errors.EvaluationException;
import org.qscript.errors.SyntaxException;

import processing.core.PApplet;

public class GraphDrawer extends PApplet {
	/**
	The sketch has two parts the top half displays the selected graph while
	the bottom half allows the user to setup the parameters for the 
	next plot. When you hit the PLOt button it will attempt to use the values
	supplied to draw the graph, if there are syntax or evaluation errors
	in the equations entered these will be highlighted. Only when the 
	equations have been successfully evaluated will the graph be updated. <br>


	This example requires the following libraries <br>
	QScript <br>
	Graphica <a href="https://github.com/jagracar/grafica">GitHub</a>
	G4P <br>
	The GUI was created with the GUI Builder tool (G4PTool)<br>
	 */
	final int CARTESIAN = 0;
	final int PARAMETRIC = 1;
	final int POLAR = 3;
	int type;

	GPlot plot;
	float gcx, gcy, gcw;
	float zf = 1.1f, czf = 1.0f;


	public void setup() {
		size(600, 620, JAVA2D);
		createGUI();
		customGUI();
		// Create plot
		plot = getPlot();
		float[] idim = plot.getDim();
		float[] mar = plot.getMar();
		gcx = idim[0]/2 + mar[1];
		gcy = idim[1]/2 + mar[2];
		gcw = idim[0];

		setType(POLAR);
		plotPolar();
	}

	public GPlot getPlot() {
		GPlot plot = new GPlot(this);
		plot.setPos(0, 0);
		plot.setBgColor(color(249, 199, 149));
		plot.setMar(new float[] {
				60, 60, 80, 20
		}
				);
		plot.setDim(390, 260);
		plot.getXAxis().setAxisLabelText("x axis");
		plot.getYAxis().setAxisLabelText("y axis");
		plot.setLineColor(0xffff0000);
		plot.activatePanning();

		return plot;
	}


	public void draw() {
		//background(251, 226, 199);
		background(249, 199, 149);
		plot.beginDraw();
		plot.drawBackground();
		plot.drawBox();
		plot.drawXAxis();
		plot.drawYAxis();
		plot.drawTitle();
		plot.drawGridLines(GPlot.BOTH);  
		plot.drawLines();
		plot.endDraw();
	}

	public void setType(int ptype) {
		type = ptype;
		pnlCart.setVisible(false);
		pnlPara.setVisible(false);
		pnlPolar.setVisible(false);
		switch(type) {
		case CARTESIAN:
			pnlCart.setVisible(true);
			break;
		case PARAMETRIC:
			pnlPara.setVisible(true);
			break;
		case POLAR:
			pnlPolar.setVisible(true);
			break;
		}
	}

	// Use this method to add additional statements
	// to customise the GUI controls
	public void customGUI() {
		pnlCart.moveTo(0, height - pnlCart.getHeight());
		pnlPolar.moveTo(0, height - pnlPolar.getHeight());
		pnlPara.moveTo(0, height - pnlPara.getHeight());

		txfPolarExpr.setText("(sin(a) * sqrt(abs(cos(a))))/(sin(a) + 1.4) - 2*sin(a) + 2");
		sdrPolarHigh.setValue(2);
	}


	public void handleSyntaxException(GLabel label, GTextField expr, SyntaxException e) {
		label.setText(e.getMessage());
		expr.addStyle(G4P.FOREGROUND, Color.BLACK, e.charNo, e.charNo + e.charWidth);
		expr.addStyle(G4P.BACKGROUND, Color.PINK, e.charNo, e.charNo + e.charWidth);
	}

	public void handleEvaluationException(GLabel label, GTextField expr, EvaluationException e) {
		label.setText(e.getMessage());
		expr.addStyle(G4P.FOREGROUND, Color.BLACK, e.charNo, e.charNo + e.charWidth);
		expr.addStyle(G4P.BACKGROUND, Color.PINK, e.charNo, e.charNo + e.charWidth);
	}


	// GUI tab
	/* =========================================================
	 * ====                   WARNING                        ===
	 * =========================================================
	 * The code in this tab has been generated from the GUI form
	 * designer and care should be taken when editing this file.
	 * Only add/edit code inside the event handlers i.e. only
	 * use lines between the matching comment tags. e.g.

	 void myBtnEvents(GButton button) { //_CODE_:button1:12356:
	 // It is safe to enter your event code here  
	 } //_CODE_:button1:12356:

	 * Do not rename this tab!
	 * =========================================================
	 */

	public void cartExpr_change(GTextField source, GEvent event) { //_CODE_:txfCartExpr:282936:
		source.clearStyles();
		lblCartStatus.setText("");
	} //_CODE_:txfCartExpr:282936:

	public void txfLowX_change(GTextField source, GEvent event) { //_CODE_:txfLowX:891008:
		source.clearStyles();
	} //_CODE_:txfLowX:891008:

	public void txfHighX_change(GTextField source, GEvent event) { //_CODE_:txfHighX:650144:
		source.clearStyles();
	} //_CODE_:txfHighX:650144:

	public void btnCart_click(GButton source, GEvent event) { //_CODE_:btnCart:733572:
		plotCartesian();
	} //_CODE_:btnCart:733572:

	public void cart1_click(GButton source, GEvent event) { //_CODE_:btnCart1:614326:
		txfCartExpr.setText("x^3 + x^2 - x");
		txfLowX.setText("-1.9");
		txfHighX.setText("1.2");
	} //_CODE_:btnCart1:614326:

	public void cart2_click(GButton source, GEvent event) { //_CODE_:btnCart2:421101:
		txfCartExpr.setText("sin(x) * cos(2.3 * x)");
		txfLowX.setText("-7");
		txfHighX.setText("7");
	} //_CODE_:btnCart2:421101:

	public void cart3_click(GButton source, GEvent event) { //_CODE_:btnCart3:265847:
		txfCartExpr.setText("log10(abs(x)) * sin(6 * x)");
		txfLowX.setText("-6.3");
		txfHighX.setText("6.3");
	} //_CODE_:btnCart3:265847:

	public void polarExpr_change(GTextField source, GEvent event) { //_CODE_:txfPolarExpr:480296:
		source.clearStyles();
		lblPolarStatus.setText("");
	} //_CODE_:txfPolarExpr:480296:

	public void highA_change(GSlider source, GEvent event) { //_CODE_:sdrPolarHigh:840952:
		//highA = source.getValueF();
		lblHighA.setText(source.getValueS());
	} //_CODE_:sdrPolarHigh:840952:

	public void btnPolarPlot_click(GButton source, GEvent event) { //_CODE_:btnPolarPlot:908431:
		plotPolar();
	} //_CODE_:btnPolarPlot:908431:

	public void sdrPolarSteps_change(GSlider source, GEvent event) { //_CODE_:sdrPolarSteps:908439:
		//  stepsPolar = source.getValueI();
		lblPolarSteps.setText(source.getValueS());
	} //_CODE_:sdrPolarSteps:908439:

	public void polar1_click(GButton source, GEvent event) { //_CODE_:btnPolar1:293407:
		txfPolarExpr.setText("(sin(a) * sqrt(abs(cos(a)))) / (sin(a) + 1.4) - 2 * sin(a) + 2");
		sdrPolarHigh.setValue(2);
		sdrPolarSteps.setValue(400);
	} //_CODE_:btnPolar1:293407:

	public void polar2_click(GButton source, GEvent event) { //_CODE_:btnPolar2:202195:
		txfPolarExpr.setText("a^1.2");
		sdrPolarHigh.setValue(10);
		sdrPolarSteps.setValue(600);
	} //_CODE_:btnPolar2:202195:

	public void polar3_click(GButton source, GEvent event) { //_CODE_:btnPolar3:477674:
		txfPolarExpr.setText("sqrt(abs(sin(a)) / (a + 0.5))");
		sdrPolarHigh.setValue(10);
		sdrPolarSteps.setValue(1800);
	} //_CODE_:btnPolar3:477674:

	public void paraExprY_change(GTextField source, GEvent event) { //_CODE_:txfParaExprY:324284:
		source.clearStyles();
		lblParaStatus.setText("");
	} //_CODE_:txfParaExprY:324284:

	public void paraExprX_change(GTextField source, GEvent event) { //_CODE_:txfParaExprX:914448:
		source.clearStyles();
		lblParaStatus.setText("");
	} //_CODE_:txfParaExprX:914448:

	public void btnPara_click(GButton source, GEvent event) { //_CODE_:btnPara:373429:
		plotParametric();
	} //_CODE_:btnPara:373429:

	public void txfLowT_change(GTextField source, GEvent event) { //_CODE_:txfLowT:706284:
		source.clearStyles();
	} //_CODE_:txfLowT:706284:

	public void txfHighT_change(GTextField source, GEvent event) { //_CODE_:txfHighT:523792:
		source.clearStyles();
	} //_CODE_:txfHighT:523792:

	public void sdrParaSteps_change(GSlider source, GEvent event) { //_CODE_:sdrParaSteps:696087:
		lblParaSteps.setText(source.getValueS());
	} //_CODE_:sdrParaSteps:696087:

	public void para1_click(GButton source, GEvent event) { //_CODE_:btnPara1:931737:
		txfParaExprY.setText("sin(t) - sin(4*t)^3");
		txfParaExprX.setText("cos(t) - cos(4*t)^3");
		txfLowT.setText("0");
		txfHighT.setText("" + TWO_PI);
		sdrParaSteps.setValue(400);
	} //_CODE_:btnPara1:931737:

	public void para2_click(GButton source, GEvent event) { //_CODE_:btnPara2:706467:
		txfParaExprY.setText("sin(t)+sin(7*t) / 2 + cos(17*t) / 3");
		txfParaExprX.setText("cos(t)+cos(7*t) / 2 + sin(17*t) / 3");
		txfLowT.setText("0");
		txfHighT.setText("" + TWO_PI);
		sdrParaSteps.setValue(400);
	} //_CODE_:btnPara2:706467:

	public void para3_click(GButton source, GEvent event) { //_CODE_:btnPara3:953478:
		txfParaExprY.setText("-3*sin(t) + 10*sin(-0.3*t)");
		txfParaExprX.setText("-3*cos(t) - 10*cos(-0.3*t)");
		txfLowT.setText("0");
		txfHighT.setText("63");
		sdrParaSteps.setValue(400);
	} //_CODE_:btnPara3:953478:

	public void btnZoomOut_click(GButton source, GEvent event) { //_CODE_:btnZoomOut:268410:
		plot.zoom(1/zf, gcx, gcy);
	} //_CODE_:btnZoomOut:268410:

	public void btnZoomIn_click(GButton source, GEvent event) { //_CODE_:btnZoomIn:817923:
		plot.zoom(zf, gcx, gcy);
	} //_CODE_:btnZoomIn:817923:

	public void optCart_click(GOption source, GEvent event) { //_CODE_:optCart:443196:
		setType(CARTESIAN);
	} //_CODE_:optCart:443196:

	public void optPolar_click(GOption source, GEvent event) { //_CODE_:optPolar:536779:
		setType(POLAR);
	} //_CODE_:optPolar:536779:

	public void optPara_click(GOption source, GEvent event) { //_CODE_:optPara:503244:
		setType(PARAMETRIC);
	} //_CODE_:optPara:503244:



	// Create all the GUI controls. 
	// autogenerated do not edit
	public void createGUI() {
		G4P.messagesEnabled(false);
		G4P.setGlobalColorScheme(GCScheme.CYAN_SCHEME);
		G4P.setCursor(ARROW);
		if (frame != null)
			frame.setTitle("Sketch Window");
		pnlCart = new GPanel(this, 0, 820, 600, 180, "Cartesian :  y = f (x)");
		pnlCart.setCollapsible(false);
		pnlCart.setDraggable(false);
		pnlCart.setText("Cartesian :  y = f (x)");
		pnlCart.setTextBold();
		pnlCart.setOpaque(true);
		txfCartExpr = new GTextField(this, 70, 30, 520, 30, G4P.SCROLLBARS_HORIZONTAL_ONLY | G4P.SCROLLBARS_AUTOHIDE);
		txfCartExpr.setText("x^3 + x^2 -x");
		txfCartExpr.setPromptText("f(x)");
		txfCartExpr.setOpaque(false);
		txfCartExpr.addEventHandler(this, "cartExpr_change");
		lblCartStatus = new GLabel(this, 70, 60, 520, 16);
		lblCartStatus.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		lblCartStatus.setLocalColorScheme(GCScheme.RED_SCHEME);
		lblCartStatus.setOpaque(true);
		lblCartY = new GLabel(this, 10, 30, 60, 20);
		lblCartY.setText("y =");
		lblCartY.setTextBold();
		lblCartY.setOpaque(false);
		label2 = new GLabel(this, 10, 80, 120, 20);
		label2.setText("Plot from x = ");
		label2.setTextBold();
		label2.setOpaque(false);
		txfLowX = new GTextField(this, 130, 80, 140, 20, G4P.SCROLLBARS_NONE);
		txfLowX.setText("-1.9");
		txfLowX.setOpaque(true);
		txfLowX.addEventHandler(this, "txfLowX_change");
		label3 = new GLabel(this, 270, 80, 30, 20);
		label3.setText("to");
		label3.setTextBold();
		label3.setOpaque(false);
		txfHighX = new GTextField(this, 300, 80, 140, 20, G4P.SCROLLBARS_NONE);
		txfHighX.setText("1.2");
		txfHighX.setOpaque(true);
		txfHighX.addEventHandler(this, "txfHighX_change");
		btnCart = new GButton(this, 510, 150, 80, 20);
		btnCart.setText("PLOT");
		btnCart.setTextBold();
		btnCart.addEventHandler(this, "btnCart_click");
		btnCart1 = new GButton(this, 300, 150, 50, 20);
		btnCart1.setText("1");
		btnCart1.setTextBold();
		btnCart1.addEventHandler(this, "cart1_click");
		btnCart2 = new GButton(this, 360, 150, 50, 20);
		btnCart2.setText("2");
		btnCart2.setTextBold();
		btnCart2.addEventHandler(this, "cart2_click");
		btnCart3 = new GButton(this, 420, 150, 50, 20);
		btnCart3.setText("3");
		btnCart3.setTextBold();
		btnCart3.addEventHandler(this, "cart3_click");
		label15 = new GLabel(this, 210, 150, 80, 20);
		label15.setText("Examples");
		label15.setTextBold();
		label15.setOpaque(false);
		pnlCart.addControl(txfCartExpr);
		pnlCart.addControl(lblCartStatus);
		pnlCart.addControl(lblCartY);
		pnlCart.addControl(label2);
		pnlCart.addControl(txfLowX);
		pnlCart.addControl(label3);
		pnlCart.addControl(txfHighX);
		pnlCart.addControl(btnCart);
		pnlCart.addControl(btnCart1);
		pnlCart.addControl(btnCart2);
		pnlCart.addControl(btnCart3);
		pnlCart.addControl(label15);
		pnlPolar = new GPanel(this, 0, 440, 600, 180, "Polar :  r = f(a)");
		pnlPolar.setCollapsible(false);
		pnlPolar.setDraggable(false);
		pnlPolar.setText("Polar :  r = f(a)");
		pnlPolar.setTextBold();
		pnlPolar.setOpaque(true);
		txfPolarExpr = new GTextField(this, 70, 30, 520, 30, G4P.SCROLLBARS_HORIZONTAL_ONLY | G4P.SCROLLBARS_AUTOHIDE);
		txfPolarExpr.setPromptText("f(a)");
		txfPolarExpr.setOpaque(false);
		txfPolarExpr.addEventHandler(this, "polarExpr_change");
		label4 = new GLabel(this, 10, 30, 60, 20);
		label4.setText("r =");
		label4.setTextBold();
		label4.setOpaque(false);
		lblPolarStatus = new GLabel(this, 69, 59, 520, 20);
		lblPolarStatus.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		lblPolarStatus.setLocalColorScheme(GCScheme.RED_SCHEME);
		lblPolarStatus.setOpaque(true);
		label5 = new GLabel(this, 10, 90, 150, 20);
		label5.setText("Plot from a = 0  to");
		label5.setTextBold();
		label5.setOpaque(false);
		lblHighA = new GLabel(this, 160, 90, 40, 20);
		lblHighA.setText("2");
		lblHighA.setOpaque(true);
		label6 = new GLabel(this, 200, 90, 30, 20);
		label6.setText("PI");
		label6.setTextBold();
		label6.setOpaque(false);
		sdrPolarHigh = new GSlider(this, 10, 110, 190, 20, 8.0f);
		sdrPolarHigh.setLimits(2.0f, 0.5f, 10.0f);
		sdrPolarHigh.setNbrTicks(20);
		sdrPolarHigh.setStickToTicks(true);
		sdrPolarHigh.setEasing(6.0f);
		sdrPolarHigh.setNumberFormat(G4P.DECIMAL, 0);
		sdrPolarHigh.setOpaque(true);
		sdrPolarHigh.addEventHandler(this, "highA_change");
		btnPolarPlot = new GButton(this, 510, 150, 80, 20);
		btnPolarPlot.setText("PLOT");
		btnPolarPlot.setTextBold();
		btnPolarPlot.addEventHandler(this, "btnPolarPlot_click");
		label11 = new GLabel(this, 230, 90, 50, 20);
		label11.setText("Steps");
		label11.setTextBold();
		label11.setOpaque(false);
		lblPolarSteps = new GLabel(this, 280, 90, 50, 20);
		lblPolarSteps.setText("400");
		lblPolarSteps.setOpaque(true);
		sdrPolarSteps = new GSlider(this, 340, 90, 250, 20, 10.0f);
		sdrPolarSteps.setLimits(400, 400, 2000);
		sdrPolarSteps.setNbrTicks(17);
		sdrPolarSteps.setStickToTicks(true);
		sdrPolarSteps.setShowTicks(true);
		sdrPolarSteps.setEasing(6.0f);
		sdrPolarSteps.setNumberFormat(G4P.INTEGER, 0);
		sdrPolarSteps.setOpaque(false);
		sdrPolarSteps.addEventHandler(this, "sdrPolarSteps_change");
		btnPolar1 = new GButton(this, 300, 150, 50, 20);
		btnPolar1.setText("1");
		btnPolar1.setTextBold();
		btnPolar1.addEventHandler(this, "polar1_click");
		btnPolar2 = new GButton(this, 360, 150, 50, 20);
		btnPolar2.setText("2");
		btnPolar2.setTextBold();
		btnPolar2.addEventHandler(this, "polar2_click");
		btnPolar3 = new GButton(this, 420, 150, 50, 20);
		btnPolar3.setText("3");
		btnPolar3.setTextBold();
		btnPolar3.addEventHandler(this, "polar3_click");
		label13 = new GLabel(this, 210, 150, 80, 20);
		label13.setText("Examples");
		label13.setTextBold();
		label13.setOpaque(false);
		pnlPolar.addControl(txfPolarExpr);
		pnlPolar.addControl(label4);
		pnlPolar.addControl(lblPolarStatus);
		pnlPolar.addControl(label5);
		pnlPolar.addControl(lblHighA);
		pnlPolar.addControl(label6);
		pnlPolar.addControl(sdrPolarHigh);
		pnlPolar.addControl(btnPolarPlot);
		pnlPolar.addControl(label11);
		pnlPolar.addControl(lblPolarSteps);
		pnlPolar.addControl(sdrPolarSteps);
		pnlPolar.addControl(btnPolar1);
		pnlPolar.addControl(btnPolar2);
		pnlPolar.addControl(btnPolar3);
		pnlPolar.addControl(label13);
		pnlPara = new GPanel(this, 0, 630, 600, 180, "Parametric : y = f(t) ,  x = g(t)");
		pnlPara.setCollapsible(false);
		pnlPara.setDraggable(false);
		pnlPara.setText("Parametric : y = f(t) ,  x = g(t)");
		pnlPara.setTextBold();
		pnlPara.setOpaque(true);
		txfParaExprY = new GTextField(this, 70, 30, 520, 30, G4P.SCROLLBARS_HORIZONTAL_ONLY | G4P.SCROLLBARS_AUTOHIDE);
		txfParaExprY.setText("sin(t) - sin(4*t)^3");
		txfParaExprY.setPromptText("f(t)");
		txfParaExprY.setOpaque(false);
		txfParaExprY.addEventHandler(this, "paraExprY_change");
		label1 = new GLabel(this, 10, 30, 60, 20);
		label1.setText("y =");
		label1.setTextBold();
		label1.setOpaque(false);
		txfParaExprX = new GTextField(this, 70, 60, 520, 30, G4P.SCROLLBARS_HORIZONTAL_ONLY | G4P.SCROLLBARS_AUTOHIDE);
		txfParaExprX.setText("cos(t) - cos(4*t)^3");
		txfParaExprX.setPromptText("g(t)");
		txfParaExprX.setOpaque(false);
		txfParaExprX.addEventHandler(this, "paraExprX_change");
		lblParaStatus = new GLabel(this, 70, 90, 520, 20);
		lblParaStatus.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		lblParaStatus.setLocalColorScheme(GCScheme.RED_SCHEME);
		lblParaStatus.setOpaque(true);
		label7 = new GLabel(this, 10, 60, 60, 20);
		label7.setText("x =");
		label7.setTextBold();
		label7.setOpaque(false);
		btnPara = new GButton(this, 510, 150, 80, 20);
		btnPara.setText("PLOT");
		btnPara.setTextBold();
		btnPara.addEventHandler(this, "btnPara_click");
		label8 = new GLabel(this, 10, 120, 100, 20);
		label8.setText("Plot from t =");
		label8.setTextBold();
		label8.setOpaque(false);
		txfLowT = new GTextField(this, 110, 120, 60, 20, G4P.SCROLLBARS_NONE);
		txfLowT.setText("0");
		txfLowT.setOpaque(true);
		txfLowT.addEventHandler(this, "txfLowT_change");
		label9 = new GLabel(this, 170, 120, 30, 20);
		label9.setText("to");
		label9.setTextBold();
		label9.setOpaque(false);
		txfHighT = new GTextField(this, 200, 120, 60, 20, G4P.SCROLLBARS_NONE);
		txfHighT.setText("10");
		txfHighT.setOpaque(true);
		txfHighT.addEventHandler(this, "txfHighT_change");
		label12 = new GLabel(this, 260, 120, 40, 20);
		label12.setText("Steps");
		label12.setTextBold();
		label12.setOpaque(false);
		lblParaSteps = new GLabel(this, 300, 120, 48, 20);
		lblParaSteps.setText("400");
		lblParaSteps.setOpaque(true);
		sdrParaSteps = new GSlider(this, 360, 120, 230, 20, 10.0f);
		sdrParaSteps.setLimits(400, 400, 2000);
		sdrParaSteps.setNbrTicks(17);
		sdrParaSteps.setStickToTicks(true);
		sdrParaSteps.setShowTicks(true);
		sdrParaSteps.setEasing(6.0f);
		sdrParaSteps.setNumberFormat(G4P.INTEGER, 0);
		sdrParaSteps.setOpaque(false);
		sdrParaSteps.addEventHandler(this, "sdrParaSteps_change");
		btnPara1 = new GButton(this, 300, 150, 50, 20);
		btnPara1.setText("1");
		btnPara1.setTextBold();
		btnPara1.addEventHandler(this, "para1_click");
		btnPara2 = new GButton(this, 360, 150, 50, 20);
		btnPara2.setText("2");
		btnPara2.setTextBold();
		btnPara2.addEventHandler(this, "para2_click");
		btnPara3 = new GButton(this, 420, 150, 50, 20);
		btnPara3.setText("3");
		btnPara3.addEventHandler(this, "para3_click");
		label14 = new GLabel(this, 210, 150, 80, 20);
		label14.setText("Examples");
		label14.setTextBold();
		label14.setOpaque(false);
		pnlPara.addControl(txfParaExprY);
		pnlPara.addControl(label1);
		pnlPara.addControl(txfParaExprX);
		pnlPara.addControl(lblParaStatus);
		pnlPara.addControl(label7);
		pnlPara.addControl(btnPara);
		pnlPara.addControl(label8);
		pnlPara.addControl(txfLowT);
		pnlPara.addControl(label9);
		pnlPara.addControl(txfHighT);
		pnlPara.addControl(label12);
		pnlPara.addControl(lblParaSteps);
		pnlPara.addControl(sdrParaSteps);
		pnlPara.addControl(btnPara1);
		pnlPara.addControl(btnPara2);
		pnlPara.addControl(btnPara3);
		pnlPara.addControl(label14);
		label10 = new GLabel(this, 0, 400, 600, 40);
		label10.setTextAlign(GAlign.LEFT, GAlign.BOTTOM);
		label10.setText("Graph Options Planner");
		label10.setTextBold();
		label10.setOpaque(true);
		btnZoomOut = new GButton(this, 536, 96, 56, 48);
		btnZoomOut.setText("Zoom\nOut");
		btnZoomOut.setTextBold();
		btnZoomOut.setTextItalic();
		btnZoomOut.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
		btnZoomOut.addEventHandler(this, "btnZoomOut_click");
		btnZoomIn = new GButton(this, 472, 96, 56, 48);
		btnZoomIn.setText("Zoom\nIn");
		btnZoomIn.setTextBold();
		btnZoomIn.setTextItalic();
		btnZoomIn.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
		btnZoomIn.addEventHandler(this, "btnZoomIn_click");
		togGroup1 = new GToggleGroup();
		optCart = new GOption(this, 320, 420, 100, 20);
		optCart.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		optCart.setText("Cartesian");
		optCart.setTextBold();
		optCart.setOpaque(false);
		optCart.addEventHandler(this, "optCart_click");
		optPolar = new GOption(this, 420, 420, 70, 20);
		optPolar.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		optPolar.setText("Polar");
		optPolar.setTextBold();
		optPolar.setOpaque(false);
		optPolar.addEventHandler(this, "optPolar_click");
		optPara = new GOption(this, 490, 420, 110, 20);
		optPara.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
		optPara.setText("Parametric");
		optPara.setTextBold();
		optPara.setOpaque(false);
		optPara.addEventHandler(this, "optPara_click");
		togGroup1.addControl(optCart);
		togGroup1.addControl(optPolar);
		optPolar.setSelected(true);
		togGroup1.addControl(optPara);
	}

	// Variable declarations 
	// autogenerated do not edit
	GPanel pnlCart; 
	GTextField txfCartExpr; 
	GLabel lblCartStatus; 
	GLabel lblCartY; 
	GLabel label2; 
	GTextField txfLowX; 
	GLabel label3; 
	GTextField txfHighX; 
	GButton btnCart; 
	GButton btnCart1; 
	GButton btnCart2; 
	GButton btnCart3; 
	GLabel label15; 
	GPanel pnlPolar; 
	GTextField txfPolarExpr; 
	GLabel label4; 
	GLabel lblPolarStatus; 
	GLabel label5; 
	GLabel lblHighA; 
	GLabel label6; 
	GSlider sdrPolarHigh; 
	GButton btnPolarPlot; 
	GLabel label11; 
	GLabel lblPolarSteps; 
	GSlider sdrPolarSteps; 
	GButton btnPolar1; 
	GButton btnPolar2; 
	GButton btnPolar3; 
	GLabel label13; 
	GPanel pnlPara; 
	GTextField txfParaExprY; 
	GLabel label1; 
	GTextField txfParaExprX; 
	GLabel lblParaStatus; 
	GLabel label7; 
	GButton btnPara; 
	GLabel label8; 
	GTextField txfLowT; 
	GLabel label9; 
	GTextField txfHighT; 
	GLabel label12; 
	GLabel lblParaSteps; 
	GSlider sdrParaSteps; 
	GButton btnPara1; 
	GButton btnPara2; 
	GButton btnPara3; 
	GLabel label14; 
	GLabel label10; 
	GButton btnZoomOut; 
	GButton btnZoomIn; 
	GToggleGroup togGroup1; 
	GOption optCart; 
	GOption optPolar; 
	GOption optPara; 


	// CARTESIAN tab
	// Cartesian plotting tab

	public void plotCartesian() {
		GPointsArray array = calcCartPoints(txfCartExpr, lblCartStatus);
		if (array != null) {
			plot = getPlot();
			String title = "Cartesian Plot\ny = " + txfCartExpr.getText();
			plot.setTitleText(title);
			plot.setPoints(array);
		}
		//parseScript(txfPolarExpr, lblPolarStatus);
	}

	public GPointsArray calcCartPoints(GTextField expr, GLabel status) {
		// Test range of x
		Float lowX = parseFloat(txfLowX.getText());
		if (lowX.isNaN())
			txfLowX.setLocalColorScheme(G4P.RED_SCHEME);
		Float highX = parseFloat(txfHighX.getText());
		if (highX.isNaN())
			txfHighX.setLocalColorScheme(G4P.RED_SCHEME);
		// If limits are invalid then return nothing
		if (lowX.isNaN() || highX.isNaN())
			return null;

		Script script = new Script(expr.getText());
		try {
			script.parse_();
		} 
		catch (SyntaxException e) {
			handleSyntaxException(lblCartStatus, expr, e);
			return null;
		}
		// Parsed OK
		GPoint[] points = new GPoint[round(gcw)];
		float range = abs(highX - lowX);
		float deltaX = range / (gcw - 1);
		lowX = min(lowX, highX);

		for (int i = 0; i < points.length; i++) {
			float x = lowX + i * deltaX;
			script.storeVariable("x", x);
			float y;
			try {
				Result result = script.evaluate_();
				y = result.answer.toFloat_();
			} 
			catch (EvaluationException e) {
				handleEvaluationException(lblCartStatus, expr, e);
				return null;
			}
			points[i] = new GPoint(x, y);
		}
		return new GPointsArray(points);
	}

	// PARAMETRIC
	// Parametric plotting tab

	public void plotParametric() {
		GPointsArray array = calcParaPoints(txfParaExprY, txfParaExprX, lblParaStatus);
		if (array != null) {
			plot = getPlot();
			String title = "Parametric Plot\ny = " + txfParaExprY.getText();
			title += "\nx = " + txfParaExprY.getText();
			plot.setTitleText(title);
			plot.setPoints(array);
		}
		//parseScript(txfPolarExpr, lblPolarStatus);
	}

	public GPointsArray calcParaPoints(GTextField exprY, GTextField exprX, GLabel status) {
		// Test range of x
		Float lowT = parseFloat(txfLowT.getText());
		if (lowT.isNaN()) {
			txfLowT.addStyle(G4P.FOREGROUND, Color.BLACK);
			txfLowT.addStyle(G4P.BACKGROUND, Color.PINK);
		}
		Float highT = parseFloat(txfHighT.getText());
		if (highT.isNaN()) {
			txfHighT.addStyle(G4P.FOREGROUND, Color.BLACK);
			txfHighT.addStyle(G4P.BACKGROUND, Color.PINK);
		}

		// If limits are invalid then return nothing
		if (lowT.isNaN() || highT.isNaN())
			return null;

		// Parse y parametric equation
		Script scriptY = new Script(exprY.getText());
		try {
			scriptY.parse_();
		} 
		catch (SyntaxException e) {
			handleSyntaxException(status, exprY, e);
			return null;
		}
		// Parse x parametric equation
		Script scriptX = new Script(exprX.getText());
		try {
			scriptX.parse_();
		} 
		catch (SyntaxException e) {
			handleSyntaxException(status, exprX, e);
			return null;
		}


		// Parsed OK
		GPoint[] points = new GPoint[sdrParaSteps.getValueI()];
		println(points.length);

		float range = abs(highT - lowT);
		float deltaT = range / (points.length - 1);

		for (int i = 0; i < points.length; i++) {
			float x, y;
			float t = lowT + i * deltaT;

			scriptY.storeVariable("t", t);
			try {
				Result result = scriptY.evaluate_();
				y = result.answer.toFloat_();
			} 
			catch (EvaluationException e) {
				handleEvaluationException(status, exprY, e);
				return null;
			}
			scriptX.storeVariable("t", t);
			try {
				Result result = scriptX.evaluate_();
				x = result.answer.toFloat_();
			} 
			catch (EvaluationException e) {
				handleEvaluationException(status, exprX, e);
				return null;
			}
			points[i] = new GPoint(x, y);
		}
		return new GPointsArray(points);
	}


	// POLAR
	// Polar plotting tab

	public void plotPolar() {
		GPointsArray array = calcPolarPoints(txfPolarExpr, lblPolarStatus);
		if (array != null) {
			plot = getPlot();
			String title = "Polar Plot\nr = " + txfPolarExpr.getText();
			plot.setTitleText(title);
			plot.setPoints(array);
		}
	}

	public GPointsArray calcPolarPoints(GTextField expr, GLabel status) {
		Script script = new Script(expr.getText());
		try {
			script.parse_();
		} 
		catch (SyntaxException e) {
			handleSyntaxException(lblPolarStatus, expr, e);
			return null;
		}
		// Parsed OK
		float maxA =  PI * sdrPolarHigh.getValueF();
		float deltaA = maxA / sdrPolarSteps.getValueI();
		GPoint[] points = new GPoint[1 + round(maxA/deltaA)];
		float a = 0;
		for (int i = 0; i < points.length; i++) {
			a = i * deltaA;
			script.storeVariable("a", a);
			float r;
			try {
				Result result = script.evaluate_();
				r = result.answer.toFloat_();
			} 
			catch (EvaluationException e) {
				handleEvaluationException(lblPolarStatus, expr, e);
				return null;
			}
			points[i] = new GPoint(r*cos(a), r*sin(a));
		}
		return new GPointsArray(points);
	}

}
